package com.bee.auth.client.util;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * @author Damin.yang
 * @date 2019/08/17 16:50
 */
@Slf4j
public class HttpSecurityUtil {

    public static final String KEY_PREFIX = "Bee:";

    public static final String TOKEN_NAME = "Authorization-Token";
    public static final String CLIENT_TOKEN_NAME = "Authorization-CLIENT";

    public static String getHeaderToken(HttpServletRequest request){
        String token = null;
        if(StringUtils.isBlank(token)){
            token = request.getHeader(TOKEN_NAME);
        }
        if(!StringUtils.isBlank(token)){
            return token;
        }
        return null;
    }

    public static String getClientToken(HttpServletRequest request){
        return request.getHeader(CLIENT_TOKEN_NAME);
    }

    public static String getToken(HttpServletRequest request){

        String token = request.getParameter(TOKEN_NAME);
        if(StringUtils.isBlank(token)){
            token = request.getHeader(TOKEN_NAME);
        }
        Cookie[] cookies = request.getCookies();
        if(cookies != null) {
            for(Cookie cookie : cookies){
                if(cookie.getName().equals(TOKEN_NAME)){
                    token = cookie.getValue();
                    break;
                }
            }
        }
        return token;
    }

    public static String createJwtToken(Map<String, Object> map, String key) {
        return createJwtToken(map, key, null);
    }

    public static String createJwtToken(Map<String, Object> map, String key, Date expire) {
        SecretKey secretKey = generalKey(key);
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        // 添加构成JWT的参数
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .setClaims(map)
                // 第三段密钥
                .signWith(signatureAlgorithm, secretKey);
        if (expire != null) {
            builder.setExpiration(expire);
        }
        //生成JWT
        return builder.compact();
    }

    public static SecretKey generalKey(String key) {
        // 本地的密码解码[B@152f6e2
        byte[] encodedKey = Base64.decodeBase64(KEY_PREFIX + key);
        // 根据给定的字节数组使用AES加密算法构造一个密钥，使用 encodedKey中的始于且包含 0 到前 leng 个字节这是当然是所有
        SecretKey secretKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return secretKey;
    }

    public static Map<String, Object> parseJwtToken(String token, String key) {
        Claims claims = parseJwt(token, key);
        return claims;
    }

    private static Claims parseJwt(String jwt, String key) {
        try {
            //签名秘钥，和生成的签名的秘钥一模一样
            SecretKey secretKey = generalKey(key);
            //得到DefaultJwtParser
            Claims claims = Jwts.parser()
                    //设置签名的秘钥
                    .setSigningKey(secretKey)
                    //设置需要解析的jwt
                    .parseClaimsJws(jwt).getBody();
            return claims;
        } catch (SignatureException | MalformedJwtException e) {
            log.info(">>> [{}] SignatureException or MalformedJwtException: {}", jwt, e.getMessage());
        } catch (ExpiredJwtException e) {
            // jwt 已经过期，在设置jwt的时候如果设置了过期时间，这里会自动判断jwt是否已经过期，如果过期则会抛出这个异常，我们可以抓住这个异常并作相关处理。
            log.info(">>> token expire: {}", jwt);
        }
        return null;
    }


}
